﻿using System;
using Microsoft.Xna.Framework;

namespace Phoenix.Xna.Framework.Input.Mice
{
    /// <summary>
    /// Tracks the state of mouse movement, allowing for complex mapping of user input to engine action.
    /// </summary>
    public class MouseAxisMap : InputMap
    {
        /// <summary>
        /// Raised when the position of the mouse changes.
        /// </summary>
        public event EventHandler<InputMapEventArgs<MouseAxisMap>> ValueChanged;

        /// <summary>
        /// Gets the current position of the mouse.
        /// </summary>
        public Vector2 CurrentPosition { get { return MouseStateManager.Instance.CurrentPosition; } }

        /// <summary>
        /// Gets the previous position of the mouse.
        /// </summary>
        public Vector2 PreviousPosition { get { return MouseStateManager.Instance.PreviousPosition; } }

        /// <summary>
        /// Gets the current change in position of the mouse.
        /// </summary>
        public Vector2 CurrentPositionDelta { get { return MouseStateManager.Instance.CurrentPositionDelta; } }

        /// <summary>
        /// Gets the previous change in position of the mouse.
        /// </summary>
        public Vector2 PreviousPositionDelta { get { return MouseStateManager.Instance.PreviousPositionDelta; } }

        /// <summary>
        /// Initializes a new instance of the MouseAxisMap class.
        /// </summary>
        public MouseAxisMap()
        {
            Register();
        }

        /// <summary>
        /// Determines if the current AxisMap is equal to the specified AxisMap.
        /// </summary>
        /// <param name="map">The AxisMap to compare to.</param>
        /// <returns>True if equal, otherwise false.</returns>
        public override bool Equals(object obj)
        {
            if (System.Object.ReferenceEquals(this, obj))
            {
                return true;
            }

            if (obj != null && obj is MouseAxisMap)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// Serves as a hash function for the AxisMap type.
        /// </summary>
        /// <returns>The hash code for this AxisMap.</returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        /// <summary>
        /// Determines if the left AxisMap is equal to the right AxisMap.
        /// </summary>
        /// <param name="left">AxisMap to the left of the operator.</param>
        /// <param name="right">AxisMap to the right of the operator.</param>
        /// <returns>True if equal, otherwise false.</returns>
        public static bool operator ==(MouseAxisMap left, MouseAxisMap right)
        {
            if (System.Object.ReferenceEquals(left, right))
            {
                return true;
            }

            if (!System.Object.ReferenceEquals(left, null))
            {
                if (System.Object.ReferenceEquals(right, null))
                {
                    return false;
                }
                else
                {
                    return left.Equals(right);
                }
            }

            return false;
        }

        /// <summary>
        /// Determines if the left AxisMap is not equal to the right AxisMap.
        /// </summary>
        /// <param name="left">AxisMap to the left of the operator.</param>
        /// <param name="right">AxisMap to the right of the operator.</param>
        /// <returns>True if not equal, otherwise false.</returns>
        public static bool operator !=(MouseAxisMap left, MouseAxisMap right)
        {
            return (left == right) ? false : true;
        }

        private void NotifyEvent(EventHandler<InputMapEventArgs<MouseAxisMap>> eventHandler)
        {
            EventHandler<InputMapEventArgs<MouseAxisMap>> handler = eventHandler;

            if (handler != null)
            {
                handler(this, new InputMapEventArgs<MouseAxisMap>(this));
            }
        }

        #region IInputMap Members

        /// <summary>
        /// Update the IInputMap.
        /// </summary>
        /// <param name="gameTime">A snapshot of the elapsed game time.</param>
        public override void Update(GameTime gameTime)
        {
            if (CurrentPosition != PreviousPosition)
            {
                NotifyEvent(ValueChanged);
            }
        }

        #endregion
    }
}
